package com.ocean;

import java.io.File;
import java.io.RandomAccessFile;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.Buffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.channels.FileLock;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.lang.reflect.Method;

import com.ocean.FileBatch.TryByteReadAdapter;
import com.ocean.FileBatch.TryByteWriteAdapter;
import com.ocean.FileBatch.TryIntReadAdapter;
import com.ocean.FileBatch.TryIntWriteAdapter;
import com.ocean.exception.FileException;
import com.ocean.util.LogUtil;

import java.util.Date;
import java.io.FilenameFilter;
import java.nio.channels.OverlappingFileLockException;

@SuppressWarnings({ "unchecked" })
public class FileAdapter extends File {
	/**
	 * 
	 */
	private static final long serialVersionUID = -8973065898962665616L;
	private RandomAccessFile raf = null;
	private FileChannel fc = null;
	private ByteBuffer mbread = null, mbwrite = null;

	public static final short[] ConstBit = new short[] { 0 << 1, 1 << 1,
			1 << 2, 1 << 3, 3 << 1, 5 << 1, 6 << 1, 7 << 1, 1 << 0 };

	public static long k(long num) {
		return 0x400 * num;
	}

	public static long m(long num) {
		return 0x400 * k(num);
	}

	public static long g(long num) {
		return 0x400 * m(num);
	}

	public FileAdapter(String filePath) {
		super(filePath);
		// fl = new File(filePath);
	}

	public FileAdapter(String parentPath, String filePath) {
		super(parentPath, filePath);
		// fl = parentPath!=null?new File(parentPath, filePath):new
		// File(filePath);
	}

	FileLock flk = null;

	public boolean readLock() {
		return readLock(0L, Long.MAX_VALUE);
	}

	public boolean readLock(long beginIndex, long bytesNum) {
		return setLock("r", 0L, Long.MAX_VALUE, true);
	}

	public boolean writeLock() {
		return writeLock(0L, Long.MAX_VALUE);
	}

	public boolean writeLock(long beginIndex, long bytesNum) {
		if (!this.exists())
			createFile(this.getPath());
		return setLock("rw", 0L, Long.MAX_VALUE, false);
	}

	boolean setLock(String rw, long beginIndex, long bytesNum, boolean s) {
		if (!this.exists())
			return false;
		try {
			raf = new RandomAccessFile(this, rw);
			fc = raf.getChannel();
			flk = fc.lock(beginIndex, bytesNum, s);
		} catch (OverlappingFileLockException oe) {
			LogUtil.warn("[SetLock]", "[No effect]",
					"the region has already been locked");
			return false;
		} catch (Exception e) {
			LogUtil.info("[SetLock]", "[No effect]", e);
			return false;
		}
		return true;
	}

	public boolean releaseLock() {
		if (!this.exists() || flk == null)
			return false;
		try {
			flk.release();
		} catch (Exception e) {
			LogUtil.info("[ReleaseLock]", "[No effect]", e);
			return false;
		}
		return true;
	}

	public static ByteReadParser getByteReadParser(byte[] array) {
		if (array == null)
			array = new byte[0];
		FileAdapter fa = new FileAdapter("");
		fa.mbread = ByteBuffer.wrap(array);
		return fa.getReader(Long.MIN_VALUE, Long.MAX_VALUE);
	}

	public static ByteReadParser getByteReadParser() {
		return getByteReadParser(null);
	}

	public interface ByteReadParser {
		public byte[] read(int totalnum);

		public byte[] readLine();

		public byte[] read(byte[] split);

		public byte[] readLast(byte[] split);

		public void jump(int num);

		public int getReadIndex();

		public short readShort();

		public int readInt();

		public long readLong();

		public float readFloat();

		public double readDouble();

		public Date readDate();

		public String readString(int length);

		public byte[] readCharsBytes(int length);

		public String readChars(int length);

		public Object readObject(int length);

		public ByteReadParser reset(byte[] array);

		public boolean reading();
	}

	public interface ByteReadAdapter extends ByteReadParser, TryByteReadAdapter {
		public byte[] readAll();

		public byte[] readAllSafety() throws FileException;
	}

	public interface IntReadAdapter extends TryIntReadAdapter {
		public int[] readIntAll();

		public int[] readIntAllSafety() throws FileException;

		public int[] readInt(int totalnum);

		public int readInt();

		public List<Integer> readListIntAll();

		public List<Integer> readListInt(int totalnum);
	}

	public interface ReadAdapter extends ByteReadAdapter, IntReadAdapter {
	}

	private boolean initRead(long beginIndex, long bytesNum) {
		if (beginIndex == Long.MIN_VALUE && bytesNum == Long.MAX_VALUE)
			return true;

		try {
			if (raf == null) {
				raf = new RandomAccessFile(this, "r");// fl
				fc = raf.getChannel();
			}

			long readnum = Math.min(this.length() - beginIndex, bytesNum);// fl
			// if(readnum==0)return false;
			mbread = fc.map(MapMode.READ_ONLY, beginIndex, readnum);
		} catch (Exception e) {
			// System.out.println(e);
			LogUtil.info("[FileAdapter]", "[ReadAdapter]", e.getMessage());
			return false;
		}
		return true;
	}

	public interface IntWriteAdapter extends TryIntWriteAdapter {
		public int writeInt(int[] its);

		public int writeIntSafety(int[] its) throws FileException;

		public int writeListInt(List<Integer> ls);
	}

	public interface ByteWriteAdapter extends TryByteWriteAdapter {
		public int write(byte[] bytes);

		public int writeSafety(byte[] bytes) throws FileException;
	}

	public interface WriteAdapter extends ByteWriteAdapter, IntWriteAdapter {
	}

	class NameFilter implements FilenameFilter {
		private String namestr;
		private boolean onlyFile = false;

		public NameFilter(String namestr, boolean onlyFile) {
			this.namestr = namestr;
			this.onlyFile = onlyFile;
		}

		@Override
		public boolean accept(File dir, String name) {
			if (name.startsWith(namestr)) {
				if (onlyFile) {
					File dirfile = new File(dir, name);
					if (dirfile.isFile())
						return true;
					else
						return false;
				} else
					return true;
			} else
				return false;
		}
	}

	public interface ByteWriteParser {
		public ByteWriteParser writeBytes(byte[] bts);

		public ByteWriteParser writeShort(short n);

		public ByteWriteParser writeInt(int n);

		public ByteWriteParser writeDouble(double n);

		public ByteWriteParser writeLong(long n);

		public ByteWriteParser writeFloat(float n);

		public ByteWriteParser writeDate(Date time);

		public ByteWriteParser writeString(String n);

		public ByteWriteParser writeCharsBytes(byte[] bts);

		public ByteWriteParser writeChars(String n);

		public ByteWriteParser writeObject(Object n);

		public int getBytesLength();

		public byte[] getBytes();

		public ByteWriteParser reset();

		public ByteWriteParser reset(int size);
	}

	public static ByteWriteParser getByteWriteParser() {
		return getByteWriteParser((int) k(512));
	}

	public static ByteWriteParser getByteWriteParser(int size) {
		FileAdapter fa = new FileAdapter("");
		return fa.getByteParserWriter(size);
	}

	public ByteWriteParser getByteParserWriter(final int size) {
		return size <= 0 ? null : new ByteWriteParser() {
			private int bytesLength = 0;
			{
				reset(size);
			}

			@Override
			public ByteWriteParser writeBytes(byte[] bts) {
				if (bts != null && bts.length > 0) {
					autoBuffer(bts.length);
					mbwrite.put(bts);
					bytesLength += bts.length;
				}
				return this;
			}

			@Override
			public ByteWriteParser writeShort(short n) {
				autoBuffer(ConstBit[1]);
				mbwrite.putShort(n);
				bytesLength += ConstBit[1];
				return this;
			}

			@Override
			public ByteWriteParser writeInt(int n) {
				autoBuffer(ConstBit[2]);
				mbwrite.putInt(n);
				bytesLength += ConstBit[2];
				return this;
			}

			@Override
			public ByteWriteParser writeDouble(double n) {
				autoBuffer(ConstBit[3]);
				mbwrite.putDouble(n);
				bytesLength += ConstBit[3];
				return this;
			}

			@Override
			public ByteWriteParser writeLong(long n) {
				autoBuffer(ConstBit[3]);
				mbwrite.putLong(n);
				bytesLength += ConstBit[3];
				return this;
			}

			@Override
			public ByteWriteParser writeFloat(float n) {
				autoBuffer(ConstBit[2]);
				mbwrite.putFloat(n);
				bytesLength += ConstBit[2];
				return this;
			}

			@Override
			public ByteWriteParser writeDate(Date time) {
				return writeLong(time.getTime());
			}

			@Override
			public ByteWriteParser writeString(String n) {
				return writeBytes(n.getBytes());
			}

			// ObjectBytes objectBytes = new ObjectBytes();
			@Override
			public ByteWriteParser writeCharsBytes(byte[] bts) {
				return writeBytes(ObjectBytes.getCharSequence(bts));
			}

			@Override
			public ByteWriteParser writeChars(String n) {
				return writeCharsBytes(n.getBytes());
			}

			@Override
			public ByteWriteParser writeObject(Object n) {
				return writeBytes(ObjectBytes.toBytes(n));
			}

			@Override
			public int getBytesLength() {
				return bytesLength;
			}

			@Override
			public byte[] getBytes() {
				byte[] btsnew = new byte[bytesLength];
				System.arraycopy(mbwrite.array(), 0, btsnew, 0, bytesLength);
				return btsnew;
			}

			@Override
			public ByteWriteParser reset() {
				// return reset(size);
				mbwrite.clear();
				bytesLength = 0;
				return this;
			}

			@Override
			public ByteWriteParser reset(int newsize) {
				mbwrite = ByteBuffer.wrap(new byte[newsize]);
				bytesLength = 0;
				return this;
			}

			private void autoBuffer(int length) {
				while (mbwrite.remaining() < length) {
					byte[] btsnew = new byte[mbwrite.capacity() + size];
					System.arraycopy(mbwrite.array(), 0, btsnew, 0, bytesLength);
					mbwrite = ByteBuffer.wrap(btsnew, bytesLength,
							btsnew.length - bytesLength);
				}
			}
		};
	}

	// ----------------
	private void initWrite() {
		try {
			if (raf == null) {
				if (!this.exists())// fl
					createFile(this.getPath());// fl
				raf = new RandomAccessFile(this, "rw");// fl
				fc = raf.getChannel();
			}
		} catch (Exception e) {
			LogUtil.info("[FileAdapter]", "[WriteAdapter]", e.getMessage());
		}
	}

	public ByteReadAdapter getByteReader() {
		return getReader();
	}

	public IntReadAdapter getIntReader() {
		return getReader();
	}

	public ReadAdapter getReader() {
		return getReader(0, this.length());// byte.length
	}

	public ByteReadAdapter getByteReader(long beginIndex, long bytesNum) {
		return getReader(beginIndex, bytesNum);
	}

	public IntReadAdapter getIntReader(long beginIndex, long intNum) {
		return getReader(beginIndex * 4, intNum * 4);
	}

	public ReadAdapter getReader(final long beginIndex, final long bytesNum) {
		if (!initRead(beginIndex, bytesNum))
			return null;
		else
			return new ReadAdapter() {
				@Override
				public void jump(int num) {
					int jumpnum = Math.min(mbread.remaining(), num);
					mbread.position(getReadIndex() + jumpnum);
				}

				@Override
				public int getReadIndex() {
					return mbread.position();
				}

				@Override
				public byte[] readAll() {
					return read((int) Math.min(bytesNum, Integer.MAX_VALUE));
				}

				@Override
				public byte[] readAllSafety() throws FileException {
					byte[] rbts = null;
					FileLock fl = null;
					try {
						fl = fc.lock(beginIndex, bytesNum, true);
						rbts = readAll();
						fl.release();
					} catch (Exception ex) {
						throw new FileException(ex);
					}
					return rbts;
				}

				@Override
				public Result<byte[]> tryReadAll() {
					return tryReadAll(false);
				}

				@Override
				public Result<byte[]> tryReadAllSafety() {
					return tryReadAll(true);
				}

				private Result<byte[]> tryReadAll(final boolean locked) {
					final FileResult<byte[]> fr = new FileResult<byte[]>(false);
					PoolExector.tpe().execute(new Runnable() {
						@Override
						public void run() {
							try {
								byte[] wh = locked ? readAllSafety()
										: readAll();
								if (wh != null)
									fr.setResult(wh);
								fr.setReady(WareHouse.READY);
							} catch (Throwable e) {
								LogUtil.info("tryReadAll", "exception", e);
								// fr.status = FileResult.EXCEPTION;
								fr.setReady(WareHouse.EXCEPTION);
							}
						}
					});
					return fr;
				}

				@Override
				public byte[] read(int totalnum) {
					int readnum = Math.min(mbread.remaining(), totalnum);
					byte[] bt = null;
					try {
						if (readnum > 0) {
							bt = new byte[readnum];
							mbread.get(bt);
						}
					} catch (Exception e) {
						LogUtil.info("[ReadAdapter]", "[read]", e.getMessage());//
					}
					return bt;
				}

				@Override
				public byte[] readLine() {
					byte[] bts = new byte[] { 0xD, 0xA };
					return read(bts);
				}

				@Override
				public byte[] read(byte[] split) {
					if (split == null || mbread.remaining() == 0)
						return null;

					int i = 0, p = mbread.position(), n = 0;
					while (mbread.hasRemaining() && i < split.length) {
						byte b = mbread.get();
						if (b == split[i]) {
							if (i++ == 0)
								mbread.mark();
						} else {
							if (i > 0) {
								mbread.reset();
								i = 0;
							}
							n++;
						}
					}

					if (i < split.length) {
						n += i;
						i = 0;
					}

					mbread.position(p);
					byte[] rbts = new byte[n];
					mbread.get(rbts);
					mbread.position(mbread.position() + i);
					return rbts;
				}

				@Override
				public byte[] readLast(byte[] split) {
					byte[] bts = readAll();

					if (split == null || bts == null)
						return null;

					int i = bts.length - 1, j = split.length - 1, m = -1;
					while (i >= 0 && j >= 0) {
						if (bts[i--] == split[j]) {
							if (j-- == split.length - 1)
								m = i;
						} else if (m > 0) {
							i = m - 1;
							j = split.length - 1;
							m = -1;
						}
					}
					return i > 0 ? Arrays.copyOf(bts, i + 1) : bts;
				}

				@Override
				public int[] readIntAll() {
					return readInt((int) (bytesNum / 4));
				}

				@Override
				public int[] readIntAllSafety() throws FileException {
					int[] rits = null;
					FileLock fl = null;
					try {
						fl = fc.lock(beginIndex, bytesNum, true);
						rits = readIntAll();
						fl.release();
					} catch (Exception ex) {
						throw new FileException(ex);
					}
					return rits;
				}

				@Override
				public Result<int[]> tryIntReadAll() {
					return tryIntReadAll(false);
				}

				@Override
				public Result<int[]> tryIntReadAllSafety() {
					return tryIntReadAll(true);
				}

				private Result<int[]> tryIntReadAll(final boolean locked) {
					final FileResult<int[]> fr = new FileResult<int[]>(false);
					PoolExector.tpe().execute(new Runnable() {
						@Override
						public void run() {
							try {
								int[] wh = locked ? readIntAllSafety()
										: readIntAll();
								if (wh != null)
									fr.setResult(wh);
								fr.setReady(WareHouse.READY);
							} catch (Throwable e) {
								LogUtil.info("tryIntReadAll", "exception", e);
								fr.setReady(WareHouse.EXCEPTION);
							}
						}
					});
					return fr;
				}

				@Override
				public int[] readInt(int totalnum) {
					int readnum = Math.min(mbread.remaining() / 4, totalnum);
					int[] its = null;
					if (readnum > 0) {
						its = new int[readnum];
						for (int i = 0; i < its.length; i++)
							its[i] = readInt();
					}
					return its;
				}

				@Override
				public List<Integer> readListIntAll() {
					return readListInt((int) (bytesNum / 4));
				}

				@Override
				public List<Integer> readListInt(int totalnum) {
					int size = Math.min(mbread.remaining() / 4, totalnum);
					List<Integer> ls = null;
					if (size > 0) {
						ls = new ArrayList<Integer>(size);
						for (int i = 0; i < size; i++)
							ls.add(readInt());
					}
					return ls;
				}

				@Override
				public boolean reading() {
					return mbread.hasRemaining();
				}

				@Override
				public int readInt() {
					int n = 0;
					try {
						n = mbread.getInt();
					} catch (Exception e) {
						LogUtil.info("[ReadAdapter]",
								"convert int data format error", e.toString());//
					}
					return n;
				}

				@Override
				public short readShort() {
					short n = 0;
					try {
						n = mbread.getShort();
					} catch (Exception e) {
						LogUtil.info("[ReadAdapter]",
								"convert short data format error", e.toString());
					}
					return n;
				}

				@Override
				public long readLong() {
					long n = 0;
					try {
						n = mbread.getLong();
					} catch (Exception e) {
						LogUtil.info("[ReadAdapter]",
								"convert long data format error", e.toString());
					}
					return n;
				}

				@Override
				public float readFloat() {
					float n = 0;
					try {
						n = mbread.getFloat();
					} catch (Exception e) {
						LogUtil.info("[ReadAdapter]",
								"convert float data format error", e.toString());
					}
					return n;
				}

				@Override
				public double readDouble() {
					double n = 0;
					try {
						n = mbread.getDouble();
					} catch (Exception e) {
						LogUtil.info("[ReadAdapter]",
								"convert double data format error",
								e.toString());
					}
					return n;
				}

				@Override
				public Date readDate() {
					long t = readLong();
					return t == 0 ? null : new Date(t);
				}

				@Override
				public String readString(int length) {
					byte[] bts = read(length);
					return bts != null ? new String(bts) : null;
				}

				// ObjectBytes objectBytes = new ObjectBytes();
				@Override
				public byte[] readCharsBytes(int length) {
					return ObjectBytes.getCharSequence(read(length));
				}

				@Override
				public String readChars(int length) {
					byte[] bts = readCharsBytes(length);
					return bts != null ? new String(bts) : null;
				}

				@Override
				public Object readObject(int length) {
					byte[] bts = read(length);
					return bts != null ? ObjectBytes.toObject(bts) : null;
				}

				@Override
				public ByteReadParser reset(byte[] array) {
					mbread = ByteBuffer.wrap(array);
					return this;
				}
			};
	}

	public File createFile() {
		return createFile(this.getPath());
	}

	public File createDirectory() {
		return createFile(this.getPath(), false);
	}

	public File createFile(String fileUrl) {
		return createFile(fileUrl, true);
	}

	public File createFile(String fileUrl, boolean fileflag) {
		File newFile = new File(fileUrl);
		try {
			if (fileflag) {
				String parentStr = newFile.getParent();
				String fileName = newFile.getName();
				File newDir = parentStr != null ? createFile(parentStr, false)
						: new File("");
				File theFile = new File(newDir, fileName);
				theFile.createNewFile();
				/*
				 * if(!theFile.createNewFile())
				 * System.out.println(fileUrl+" already existed!");
				 */
			} else {
				if (!newFile.exists())
					newFile.mkdirs();
			}
		} catch (Exception e) {
			LogUtil.info("[FileAdapter]", "[createFile]", e.getMessage() + ":"
					+ fileUrl);
		}
		return newFile;
	}

	public ByteWriteAdapter getByteWriter() {
		return getWriter();
	}

	public IntWriteAdapter getIntWriter() {
		return getWriter();
	}

	public WriteAdapter getWriter() {
		return getWriter(-1, -1);
	}

	public ByteWriteAdapter getByteWriter(long beginIndex, long bytesNum) {
		return getWriter(beginIndex, bytesNum);
	}

	public IntWriteAdapter getIntWriter(long beginIndex, long intNum) {
		return getWriter(beginIndex * 4, intNum * 4);
	}

	public WriteAdapter getWriter(final long beginIndex, final long bytesNum) {
		initWrite();
		final long filesize = this.length();
		return new WriteAdapter() {
			private long index, num;

			private void initIndexNum(long t) {
				index = beginIndex < 0 ? filesize : beginIndex;
				num = bytesNum < 0 ? t : bytesNum;
			}

			private void initWriteBuffer(int total) throws IOException {
				initIndexNum(total);
				mbwrite = fc.map(MapMode.READ_WRITE, index, num);
			}

			@Override
			public int write(byte[] bytes) {
				int t = 0;
				try {
					initWriteBuffer(bytes.length);
					if (bytes.length > num)// mbread.remaining()
						bytes = Arrays.copyOf(bytes, (int) num);
					mbwrite.put(bytes);
					t = bytes.length;
				} catch (Exception e) {
					LogUtil.info("[WriteAdapter]", "[write]", e.getMessage());//
				}
				return t;
			}

			/*
			 * public int writeSafety(byte[] bytes) throws FileException{ int t
			 * = 0; FileLock fl = null; try{ initIndexNum(bytes.length); fl =
			 * fc.lock(index,num,false);// t = write(bytes);//raf.write(1);
			 * fl.release();// }catch(Exception ex){ throw new
			 * FileException(ex); } return t; }
			 */

			@Override
			public int writeSafety(byte[] bytes) throws FileException {
				return writeSafety(bytes, null);
			}

			private int writeSafety(byte[] bytes, int[] its)
					throws FileException {
				int t = 0;
				FileLock fl = null;
				try {
					if (bytes != null)
						initIndexNum(bytes.length);
					else
						initIndexNum(its.length * 4);
					fl = fc.lock(index, num, false);
					t = bytes != null ? write(bytes) : writeInt(its);
					fl.release();
				} catch (Exception ex) {
					throw new FileException(ex);
				}
				return t;
			}

			private int write(byte[] bytes, int[] its) {
				return bytes != null ? write(bytes) : writeInt(its);
			}

			@Override
			public Result<Integer> tryWrite(byte[] bytes) {
				return tryWrite(bytes, null, false);
			}

			@Override
			public Result<Integer> tryWriteSafety(byte[] bytes) {
				return tryWrite(bytes, null, true);
			}

			/*
			 * private Result<Integer> tryWrite(final byte[] bytes, final
			 * boolean locked) { final FileResult<Integer> fr = new
			 * FileResult<Integer>(false); PoolExector.tpe().execute(new
			 * Runnable(){ public void run(){ try{ int bl =
			 * locked?writeSafety(bytes):write(bytes); fr.setResult(new
			 * Integer(bl)); //fr.setReady(true); fr.setReady(FileResult.READY);
			 * }catch(Throwable e){ LogUtil.info("tryWrite", "exception", e);
			 * //fr.status = FileResult.EXCEPTION;
			 * fr.setReady(FileResult.EXCEPTION); } } }); return fr; }
			 */

			private Result<Integer> tryWrite(final byte[] bytes,
					final int[] its, final boolean locked) {
				final FileResult<Integer> fr = new FileResult<Integer>(false);
				PoolExector.tpe().execute(new Runnable() {
					@Override
					public void run() {
						try {
							int bl = locked ? writeSafety(bytes, its) : write(
									bytes, its);
							fr.setResult(new Integer(bl));
							// fr.setReady(true);
							fr.setReady(WareHouse.READY);
						} catch (Throwable e) {
							LogUtil.info("tryWrite", "exception", e);
							// fr.status = FileResult.EXCEPTION;
							fr.setReady(WareHouse.EXCEPTION);
						}
					}
				});
				return fr;
			}

			@Override
			public int writeInt(int[] its) {
				int i = 0;
				try {
					initWriteBuffer(its.length * 4);
					int wt = Math.min((int) (num / 4), its.length);
					for (; i < wt; i++)
						mbwrite.putInt(its[i]);
				} catch (Exception e) {
					LogUtil.info("[WriteAdapter]", "[writeInt]", e.getMessage());
				}
				return i;
			}

			/*
			 * public int writeIntSafety(int[] its) throws FileException { int t
			 * = 0; FileLock fl = null; try{ initIndexNum(its.length*4); fl =
			 * fc.lock(index,num,false); t = writeInt(its); fl.release();
			 * }catch(Exception ex){ throw new FileException(ex); } return t; }
			 */

			@Override
			public int writeIntSafety(int[] its) throws FileException {
				return writeSafety(null, its);
			}

			@Override
			public Result<Integer> tryIntWrite(int[] its) {
				return tryWrite(null, its, false);
			}

			@Override
			public Result<Integer> tryIntWriteSafety(int[] its) {
				return tryWrite(null, its, true);
			}

			/*
			 * private Result<Integer> tryIntWrite(final int[] its, final
			 * boolean locked) { final FileResult<Integer> fr = new
			 * FileResult<Integer>(false); PoolExector.tpe().execute(new
			 * Runnable(){ public void run(){ try{ int bl =
			 * locked?writeIntSafety(its):writeInt(its); fr.setResult(new
			 * Integer(bl)); fr.setReady(FileResult.READY); }catch(Throwable e){
			 * LogUtil.info("tryIntWrite", "exception", e);
			 * fr.setReady(FileResult.EXCEPTION); } } }); return fr; }
			 */

			@Override
			public int writeListInt(List<Integer> ls) {
				int i = 0;
				try {
					initWriteBuffer(ls.size() * 4);
					int wt = Math.min((int) (num / 4), ls.size());
					for (; i < wt; i++)
						mbwrite.putInt(ls.get(i));
				} catch (Exception e) {
					LogUtil.info("[WriteAdapter]", "[writeListInt]",
							e.getMessage());
				}
				return i;
			}
		};
	}

	/*
	 * public boolean exists() { return fl.exists(); }
	 * 
	 * public boolean isFile() { return fl.isFile(); }
	 * 
	 * public String getPath() { return fl.getPath(); }
	 * 
	 * 
	 * public boolean delete() { close(); boolean b = false; try{ b =
	 * fl.delete(); }catch(Exception e){ System.out.println(e); } return b; }
	 */

	public int copyTo(String toFilePath) {
		return copyTo(toFilePath, FileAdapter.m(8));
	}

	public int copyTo(String toFilePath, long every) {
		int c = 0;
		FileAdapter fa = new FileAdapter(toFilePath);
		fa.createFile();
		byte[] bts = null;
		long begin = 0;
		while ((bts = this.getReader(begin, every).readAll()) != null) {
			c += fa.getWriter().write(bts);
			begin += bts.length;
		}
		fa.close();
		return c;
	}

	public Result<Integer> tryCopyTo(String toFilePath) {
		return tryCopyTo(toFilePath, FileAdapter.m(8));
	}

	public Result<Integer> tryCopyTo(final String toFilePath, final long every) {
		final FileResult<Integer> fr = new FileResult<Integer>(false);
		PoolExector.tpe().execute(new Runnable() {
			@Override
			public void run() {
				try {
					int bl = copyTo(toFilePath, every);
					fr.setResult(new Integer(bl));
					fr.setReady(WareHouse.READY);
				} catch (Throwable e) {
					LogUtil.info("tryCopyFile", "exception", e);
					fr.setReady(WareHouse.EXCEPTION);
				}
			}
		});
		return fr;
	}

	public final void closeBuffer(final Buffer buffer) {
		if (null == buffer)
			return;
		AccessController.doPrivileged(new PrivilegedAction<Object>() {
			@Override
			public Object run() {
				try {
					Method cleanerMethod = buffer.getClass().getMethod(
							"cleaner");
					if (null == cleanerMethod)
						return null;
					cleanerMethod.setAccessible(true);
					Object cleanerObj = cleanerMethod.invoke(buffer);
					if (null == cleanerObj)
						return null;
					Method cleanMethod = cleanerObj.getClass().getMethod(
							"clean");
					if (null == cleanMethod)
						return null;
					cleanMethod.invoke(cleanerObj);
				} catch (Throwable e) {
				}
				return null;
			}
		});
	}

	public void closeExit() {
		PoolExector.close();
		close();
	}

	public void close() {
		try {
			if (fc != null)
				fc.close();
			if (raf != null)
				raf.close();
			closeBuffer(mbread);
			closeBuffer(mbwrite);
		} catch (Exception e) {
			LogUtil.info("[FileAdapter]", "[close]", e.getMessage());
		}
	}

	public static void main(String[] args) {
	}
}